#include "Terrain.h"

using namespace std;

Terrain::Terrain(int numVertices)
//Terrain::Terrain()
{
	Terrain::numVertices = numVertices;
	heightGrid = new Vertex[numVertices];
	Terrain::mult = 500;
	noise = PerlinNoise(1.10,2.0,8);

/*	for (int i=0; i < numVertices; i++) {
		float x = i%(int) sqrt((float) numVertices);
		float z = i/(int) sqrt((float) numVertices);
		float y = noise.perlNoise2D(x,z,true);

		cout << x << "," << y << "," << z << endl;
		heightGrid[i] = Vertex(x,y,z,0,0,0);
	}*/

	for(int i = 0; i < (int) sqrt((double) numVertices); i++)
	{
		for(int j = 0; j < (int) sqrt((double) numVertices); j++)
		{
			heightGrid[(int) sqrt((double) numVertices)*i+j].SetPosX((float)i*mult);
			heightGrid[(int) sqrt((double) numVertices)*i+j].SetPosZ((float)j*mult);
			heightGrid[(int) sqrt((double) numVertices)*i+j].SetPosY(noise.perlNoise2D(i*mult,j*mult,false)*(mult/10));
		}
	}
}

Terrain::~Terrain(void)
{
	cout << "Deleting Terrain.";
}

GeomNode *Terrain::getGrid()
{
	GeomNode *grid = BuildGrid(Terrain::heightGrid, Terrain::numVertices);
	return grid;
}

float Terrain::getHeight(float x, float z)
{	
	int mymult = 300;
	PerlinNoise mynoise = PerlinNoise(1.10,2.0,8);
	return mynoise.perlNoise2D(x*mymult,z*mymult,false)*(mymult);
}

std::list<WorldObject *> Terrain::getTerrain(float minX, float maxX, float minZ, float maxZ)
{
	std::list<WorldObject *> segments;
	int magnitude = 0;
	test = false;
	int size;
	float num = ((maxX-minX)+(maxZ-minZ))/2;

	for (int i=0; num/10>=1.0; i++)
	{
		num = num/10;
		magnitude = i;
	}

	size = pow((double) 10, (double) magnitude);

	Vect3D * tLMo = triangleLeftMost(minX, maxX, minZ, maxZ);
	Vect3D * tLMi = triangleLeftMid(minX, maxX, minZ, maxZ);
	Vect3D * tRMi = triangleRightMid(minX, maxX, minZ, maxZ);
	Vect3D * tRMo = triangleRightMost(minX, maxX, minZ, maxZ);

	segments.push_back(new TerrainSegment(tLMo[1],tLMo[2],tLMo[3], size));
	segments.push_back(new TerrainSegment(tLMi[1],tLMi[2],tLMi[3], size));
	segments.push_back(new TerrainSegment(tRMi[1],tRMi[2],tRMi[3], size));
	segments.push_back(new TerrainSegment(tRMo[1],tRMo[2],tRMo[3], size));

	return segments;
}

Vect3D *Terrain::triangleLeftMost(int minX, int maxX, int minZ, int maxZ)
{
	Vect3D *corners = new Vect3D[3];

	corners[0].x = minX;
	corners[0].y = noise.perlNoise2D(minX*mult,minZ*mult,false)*(mult/10);
	corners[0].z = minZ;
	corners[1].x = minX;
	corners[1].y = noise.perlNoise2D(minX*mult,maxZ*mult,false)*(mult/10);
	corners[1].z = maxZ;
	corners[2].x = (maxX-minX)/2;
	corners[2].y = noise.perlNoise2D(((maxX-minX)/2)*mult,minZ*mult,false)*(mult/10);
	corners[2].z = minZ;

	if (test)
		testTerrain(corners);
	
	return corners;
}

Vect3D *Terrain::triangleLeftMid(int minX, int maxX, int minZ, int maxZ)
{
	Vect3D *corners = new Vect3D[3];

	corners[0].x = minX;
	corners[0].y = noise.perlNoise2D(minX*mult,maxZ*mult,false)*(mult/10);
	corners[0].z = maxZ;
	corners[1].x = (maxX-minX)/2;
	corners[1].y = noise.perlNoise2D((maxX-minX)/2*mult,maxZ*mult,false)*(mult/10);
	corners[1].z = maxZ;
	corners[2].x = (maxX-minX)/2;
	corners[2].y = noise.perlNoise2D((maxX-minX)/2*mult,minZ*mult,false)*(mult/10);
	corners[2].z = minZ;

	if (test)
		testTerrain(corners);
	
	return corners;
}

Vect3D *Terrain::triangleRightMid(int minX, int maxX, int minZ, int maxZ)
{
	Vect3D *corners = new Vect3D[3];

	corners[0].x = (maxX-minX)/2;
	corners[0].y = noise.perlNoise2D((maxX-minX)/2*mult,minZ*mult,false)*(mult/10);
	corners[0].z = minZ;
	corners[1].x = (maxX-minX)/2;
	corners[1].y = noise.perlNoise2D((maxX-minX)/2*mult,maxZ*mult,false)*(mult/10);
	corners[1].z = maxZ;
	corners[2].x = maxX;
	corners[2].y = noise.perlNoise2D(maxX*mult,minZ*mult,false)*(mult/10);
	corners[2].z = maxZ;

	if (test)
		testTerrain(corners);

	return corners;
}

Vect3D *Terrain::triangleRightMost(int minX, int maxX, int minZ, int maxZ)
{
	Vect3D *corners = new Vect3D[3];

	corners[0].x = (maxX-minX)/2;
	corners[0].y = noise.perlNoise2D((maxX-minX)/2*mult,maxZ*mult,false)*(mult/10);
	corners[0].z = maxZ;
	corners[1].x = maxX;
	corners[1].y = noise.perlNoise2D(maxX*mult,maxZ*mult,false)*(mult/10);
	corners[1].z = maxZ;
	corners[2].x = maxX;
	corners[2].y = noise.perlNoise2D(maxX*mult,minZ*mult,false)*(mult/10);
	corners[2].z = minZ;

	if (test)
		testTerrain(corners);

	return corners;
}

void Terrain::testTerrain(Vect3D *corners)
{
	std::cout << "(" << corners[0].x << ", " << corners[0].y << ", " << corners[0].z << ")\n";
	std::cout << "(" << corners[1].x << ", " << corners[1].y << ", " << corners[1].z << ")\n";
	std::cout << "(" << corners[2].x << ", " << corners[2].y << ", " << corners[2].z << ")\n";

	return;
}

void Terrain::setMultiplier(int mult)
{
	Terrain::mult = mult;

	return;
}

void Terrain::setNoise(float per, float freq, float oct)
{
	noise = PerlinNoise(per, freq, oct);
}

/*
int main(void)
{
	std::list<WorldObject *> tSegs;
	Terrain * test = new Terrain();
	
	tSegs = test->getTerrain(0,1000,0,1000);
	cout << tSegs.pop_back().getA();
}*/
